package com.zecan.blog.service.impl;

import com.zecan.blog.common.status.BlogCommonStatus;
import com.zecan.blog.common.status.UserStatus;
import com.zecan.blog.controller.exception.BlogException;
import com.zecan.blog.controller.exception.UserException;
import com.zecan.blog.dao.*;
import com.zecan.blog.dao.converter.BlogArticleConverter;
import com.zecan.blog.dto.atricle.ArticleDto;
import com.zecan.blog.dto.atricle.UserArticleDto;
import com.zecan.blog.entity.Article;
import com.zecan.blog.entity.BlogUser;
import com.zecan.blog.entity.StarGood;
import com.zecan.blog.service.ArticleService;
import com.zecan.blog.utils.AliOssUtils;
import com.zecan.blog.utils.StringUtils;
import com.zecan.blog.vo.achives.ArchivesVo;
import com.zecan.blog.vo.article.ArticleMsgVo;
import com.zecan.blog.vo.article.BlogIndexArticleVo;
import com.zecan.blog.vo.user.UserArticleVo;
import com.zecan.blog.vo.stargood.StarArticleVo;
import com.zecan.blog.vo.user.UserBlogVo;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;

/**
 * @ClassName ArticleServiceImpl
 * @Description
 * @date 2022/10/28 17:57
 * @Version 1.0
 * ArticleService 实现类
 */
@Service
public class ArticleServiceImpl implements ArticleService {

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private AliOssUtils aliOssUtils;

    @Resource
    private UserMapper userMapper;

    @Resource
    private TagMapper tagMapper;

    @Resource
    private ClassifyMapper classifyMapper;

    @Resource
    private StarGoodMapper starGoodMapper;


    @Resource
    private FollowMapper followMapper;

    @Override
    public List<BlogIndexArticleVo> getArticleList(Integer offset, Integer limit) throws ParseException {
        List<Article> articleList = articleMapper.findArticleList(offset, limit);
        List<BlogIndexArticleVo> articleMsgVos  = new ArrayList<>();

        for (Article article : articleList) {
            articleMsgVos.add(BlogIndexArticleVo.buildBlogIndexArticleVo( article));
        }
        return articleMsgVos;
    }

    @Override
    public Integer getArticleCount() {
        return articleMapper.findArticleCount();
    }

    @Override
    public UserBlogVo getArticleListByUserId(UserArticleDto articleDto) {
        Long userId = articleDto.getUserId();
        Integer offset = articleDto.getOffset();
        Integer limit = articleDto.getLimit();

        // 判断当前是否有用户id
        if(Objects.isNull(userId)){
            throw new BlogException(BlogCommonStatus.NULL_POINT_ERROR);
        }
        // 获取文章信息
        List<Article> articleListByUserId = articleMapper.findArticleListByUserId(userId, offset, limit);
        if(Objects.isNull(articleListByUserId)) {
            throw new BlogException(BlogCommonStatus.REQUEST_DATA_ERROR);
        }
        // 返回前端的vo
        List<UserArticleVo> userArticleVoList = new ArrayList<>();


        // 数据整合
        for (Article article : articleListByUserId) {
            userArticleVoList.add( UserArticleVo.buildUserArticle(article));
        }

        // 获取用户发布的文章数量
        Integer count = articleMapper.findUserArticleCount(userId);
        return UserBlogVo.builder().userArticleVos(userArticleVoList).userBlogCount(count).build();
    }

    @Override
    public String getUserArticleContent(Integer articleId) {
        return articleMapper.findUserArticleContent(articleId);
    }

    @Override
    public ArticleMsgVo getArticleByArticleId(Integer articleId,Integer userId) {
        // 是否是正确的文章id
        if(articleId <= 0) {
            throw new BlogException(BlogCommonStatus.REQUEST_DATA_ERROR);
        }
        //文章id是否存在
        if(articleMapper.checkArticleIsExist(articleId).equals(0)) {
            throw new UserException(UserStatus.USER_ARTICLE_IS_NOT_EXIST);
        }
        //数据获取
        Article article = articleMapper.findArticle(articleId);
        //获取当前用户对文章点赞和收藏信息
        StarGood starGood = null;
        if(userId != null) {
            starGood  = starGoodMapper.findStarGoodByUserIdAndArticleId(articleId, userId);
        }
        // 获取当前登录用户是否关注过文章用户
        Integer follow = followMapper.findFollowById(Math.toIntExact(article.getArticleAuthorId()), userId);

        if(starGood != null) {
            return ArticleMsgVo.buildArticleMsgVo(article,starGood.getIsGood()==1,starGood.getIsStar()==1,follow != null && follow == 0);
        }
        return ArticleMsgVo.buildArticleMsgVo(article,false,false,follow != null && follow == 0);
    }

    @Override
    public void delArticle(Integer articleId) {
        Integer col = articleMapper.updateArticleStatus(articleId);

        //删除文章后 要把对应的收藏表中的信息也删除
        starGoodMapper.deleteStarGood(articleId);

        if(col != 1) {
            throw new BlogException(BlogCommonStatus.DEL_ERR);
        }

    }

    @Override
    public Integer addArticle(Article article) {
        // 获取操作用户
        String loginUserName = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        BlogUser userByUsername = userMapper.findUserByUsername(loginUserName);

        // 初始化信息
        article.setArticleAuthorId(userByUsername.getUserId());
        article.setArticleStatus(0);
        article.setArticleViews(0);
        article.setArticleLikeCount(0);
        article.setArticleCreateTime(StringUtils.dateFormat(new Date()));
        //如果用户没有上传背景图
        if(article.getArticleImage().equals("")) {
            article.setArticleImage("https://map-zblog.oss-cn-guangzhou.aliyuncs.com/article/articleImg/1b33d002-9224-485b-a257-c3131b6e36d0.png");
        }
        //添加
        Integer integer = articleMapper.insertArticle(article);
        // 不为1则添加失败
        if(integer != 1) {
            throw new UserException(UserStatus.USER_ARTICLE_SEND_ERR);
        }
        // 返回id
        return article.getArticleId();
    }

    @Override
    public void updateArticle(ArticleDto articleDto) {
        Integer articleId = articleDto.getArticleId();
        Integer articleIsDel = articleMapper.checkArticleIsExist(articleId);
        // 文章状态判定
        if(articleIsDel.equals(0)) {
            throw new UserException(UserStatus.USER_ARTICLE_IS_NOT_EXIST);
        }
        //修改文章
        Integer integer = articleMapper.updateArticleMsg(BlogArticleConverter.INSTANCE.articleConvertEntity(articleDto));
        if(integer.equals(0)) {
            throw new BlogException(BlogCommonStatus.REQUEST_DATA_ERROR);
        }
        // 修改完成
    }

    @Override
    public String uploadArticleImage(MultipartFile multipartFile) {
        try {
           return  aliOssUtils.upload(multipartFile.getInputStream(),"article/articleImg",multipartFile.getOriginalFilename());
        } catch (IOException e) {
            throw new BlogException(BlogCommonStatus.UPLOAD_IMAGE_FAIL);
        }
    }

    @Override
    public String uploadMarkdownImage(MultipartFile multipartFile) {
        try {
            return  aliOssUtils.upload(multipartFile.getInputStream(),"article/markdownImg",multipartFile.getOriginalFilename());
        } catch (IOException e) {
            throw new BlogException(BlogCommonStatus.UPLOAD_IMAGE_FAIL);
        }
    }

    @Override
    public StarArticleVo getUserFavorite(UserArticleDto userArticleDto) {

        Long userId = userArticleDto.getUserId();
        Integer offset = userArticleDto.getOffset();
        Integer limit = userArticleDto.getLimit();

        List<Article> articleListByUserIdStar = articleMapper.findArticleListByUserIdStar(userId,offset,limit);
        List<ArticleMsgVo> articleMsgVoList = new ArrayList<>();
        // 获取用户的收藏信息
        articleListByUserIdStar.forEach(article -> articleMsgVoList.add(ArticleMsgVo.buildArticleMsgVo(article,false,false,false)));
        //获取用户的收藏数量

        Integer starCount = starGoodMapper.findStarCount(userId);

        return StarArticleVo.builder().articleMsgVoList(articleMsgVoList).starCount(starCount).build();
    }

    @Override
    public List<ArchivesVo> getArticleArchives() {
        List<Article> articleArchives = articleMapper.findArticleArchives();
        List<ArchivesVo> archivesVos = new ArrayList<>();
        if(articleArchives != null) {
            articleArchives.forEach(article -> {
                archivesVos.add(ArchivesVo.convertArchivesVo(article));
            });
        }
        return archivesVos;
    }
}
